package mapbox;

import android.animation.ObjectAnimator;
import android.animation.TypeEvaluator;
import android.animation.ValueAnimator;
import android.graphics.PointF;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentTransaction;
import android.support.v7.app.AppCompatActivity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;

import com.google.gson.JsonElement;
import com.mapbox.mapboxsdk.annotations.Marker;
import com.mapbox.mapboxsdk.annotations.MarkerViewOptions;
import com.mapbox.mapboxsdk.camera.CameraPosition;
import com.mapbox.mapboxsdk.geometry.LatLng;
import com.mapbox.mapboxsdk.maps.MapView;
import com.mapbox.mapboxsdk.maps.MapboxMap;
import com.mapbox.mapboxsdk.maps.MapboxMapOptions;
import com.mapbox.mapboxsdk.maps.OnMapReadyCallback;
import com.mapbox.mapboxsdk.maps.SupportMapFragment;
import com.mapbox.mapboxsdk.maps.UiSettings;
import com.mapbox.mapboxsdk.maps.widgets.CompassView;
import com.mapbox.mapboxsdk.style.layers.Layer;
import com.mapbox.mapboxsdk.style.layers.RasterLayer;
import com.mapbox.mapboxsdk.style.sources.RasterSource;
import com.mapbox.mapboxsdk.style.sources.TileSet;
import com.mapbox.mapboxsdk.utils.MapFragmentUtils;
import com.mapbox.services.commons.geojson.Feature;

import java.lang.ref.WeakReference;
import java.util.List;
import java.util.Map;

import library.logger.Logger;

import static com.mapbox.mapboxsdk.style.layers.Property.NONE;
import static com.mapbox.mapboxsdk.style.layers.Property.VISIBLE;
import static com.mapbox.mapboxsdk.style.layers.PropertyFactory.visibility;


/**
 * Created by Mr.Fan on 2017/4/3.
 */

public class MapFragment extends SupportMapFragment {
    private static final int ZOOM = 9;
    private static final int MIN_ZOOM = 1;
    private static final int MAX_ZOOM = 20;
    private static final int TILE_SIZE = (int) (256);
    private ValueAnimator mMarkerAnimator;
    private WeakReference<MapView> mMapViewWeakReference;
    private WeakReference<MapboxMap> mMapboxMapWeakReference;

    public static MapFragment install(AppCompatActivity activity, int resId) {
        final String tag = "mapbox";
        final FragmentManager fragmentManager = activity.getSupportFragmentManager();
        MapFragment mapFragment;
        mapFragment = (MapFragment) fragmentManager.findFragmentByTag(tag);
        if (mapFragment == null) {

            MapboxMapOptions options = new MapboxMapOptions();
            String style = "mapbox/style-background.json";
            options.styleUrl("asset://" + style);
            options.camera(new CameraPosition.Builder()
                    .target(new LatLng(40.17388923655763, 116.47226572036743))
//                    .tilt(5)
//                    .bearing(10)
                    .zoom(ZOOM)
                    .build());

            mapFragment = new MapFragment();
            mapFragment.setArguments(MapFragmentUtils.createFragmentArgs(options));


            final FragmentTransaction transaction = fragmentManager.beginTransaction();

            transaction.add(resId, mapFragment, tag);
            transaction.commit();
        }
        return mapFragment;
    }

    @Override
    public void onDestroyView() {
        super.onDestroyView();
    }

    public MapView getMapView() {
        return mMapViewWeakReference != null ? mMapViewWeakReference.get() : null;
    }

    public MapboxMap getMapboxMap() {
        return mMapboxMapWeakReference != null ? mMapboxMapWeakReference.get() : null;
    }

    public void toggleLayer(String layerName) {
        Layer layer = getMapboxMap().getLayer(layerName);
        if (layer != null) {
            if (VISIBLE.equals(layer.getVisibility().getValue())) {
                layer.setProperties(visibility(NONE));
            } else {
                layer.setProperties(visibility(VISIBLE));
            }
        }

    }


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        MapView mMapView = getMapView();
        if (mMapView == null) {
            mMapView = (MapView) super.onCreateView(inflater, container, savedInstanceState);
            mMapViewWeakReference = new WeakReference<MapView>(mMapView);
            try {
                //初始化时 隐藏 指南针和商标 等View
                CompassView compassView = (CompassView) mMapView.findViewById(com.mapbox.mapboxsdk.R.id.compassView);
                ImageView logoView = (ImageView) mMapView.findViewById(com.mapbox.mapboxsdk.R.id.logoView);
                ImageView attrView = (ImageView) mMapView.findViewById(com.mapbox.mapboxsdk.R.id.attributionView);
                compassView.setVisibility(View.GONE);
                logoView.setVisibility(View.GONE);
                attrView.setVisibility(View.GONE);
            } catch (Exception e) {
                Logger.debug(e);
            }
            getMapAsync(new OnMapReadyCallback() {
                @Override
                public void onMapReady(MapboxMap mapboxMap) {
                    mMapboxMapWeakReference = new WeakReference<>(mapboxMap);
                    initMapBox(mapboxMap);
                    initLayer(mapboxMap);

                }
            });
        }
        return mMapView;
    }

    private void initLayer(MapboxMap mapboxMap) {
        final String id_google = "tile-google";
        final String id_st = "title-st";
        if (mapboxMap.getLayer(id_st) == null) {
            if (mapboxMap.getSource(id_st) == null) {
                TileSet tileSet = new TileSet(id_st, "http://mt3.google.cn/vt/lyrs=y@258000000&hl=zh-CN&gl=CN&x={x}&y={y}&z={z}");
                RasterSource rasterSource = new RasterSource(id_st, tileSet, TILE_SIZE);
                mapboxMap.addSource(rasterSource);
                RasterLayer rasterLayer = new RasterLayer(id_st, id_st);
                mapboxMap.addLayerAbove(rasterLayer, "background");
            }
        }

        if (mapboxMap.getLayer(id_google) == null) {
            if (mapboxMap.getSource(id_google) == null) {
                TileSet tileSet = new TileSet(id_google, "http://mt3.google.cn/vt/lyrs=m@162000000&hl=zh-CN&gl=cn&x={x}&y={y}&z={z}");
                RasterSource rasterSource = new RasterSource(id_google, tileSet, TILE_SIZE);
                mapboxMap.addSource(rasterSource);
            }
            RasterLayer rasterLayer = new RasterLayer(id_google, id_google);
            mapboxMap.addLayerAbove(rasterLayer, "background");
        }

        mapboxMap.setOnCameraChangeListener(new MapboxMap.OnCameraChangeListener() {
            int zoom;

            @Override
            public void onCameraChange(CameraPosition position) {
                int zoom = (int) position.zoom;
                if (this.zoom != zoom) {
                    onZoomChange(this.zoom = zoom);
                }
            }

            private void onZoomChange(int zoom) {
//                Tips.obtain(getContext()).toast("zoom " + zoom);
            }

        });

        mapboxMap.setOnMarkerClickListener(new MapboxMap.OnMarkerClickListener() {
            @Override
            public boolean onMarkerClick(@NonNull Marker marker) {
                return true;
            }
        });
        mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
            Marker marker;

            @Override
            public void onMapClick(@NonNull LatLng point) {
                if (true) {
                    return;
                }
                if (marker != null) {
                    mapboxMap.removeMarker(marker);
                }

                final PointF pixel = mapboxMap.getProjection().toScreenLocation(point);
                List<Feature> features = mapboxMap.queryRenderedFeatures(pixel);

                if (features.size() > 0) {
                    Feature feature = features.get(0);

                    String property;

                    StringBuilder stringBuilder = new StringBuilder();
                    if (feature.getProperties() != null) {
                        for (Map.Entry<String, JsonElement> entry : feature.getProperties().entrySet()) {
                            stringBuilder.append(String.format("%s - %s", entry.getKey(), entry.getValue()));
                            stringBuilder.append(System.getProperty("line.separator"));
                        }

                        marker = mapboxMap.addMarker(new MarkerViewOptions()
                                .position(point)
                                .title("Properties:")
                                .snippet(stringBuilder.toString())
                        );

                    } else {
                        property = "No feature properties found";
                        marker = mapboxMap.addMarker(new MarkerViewOptions()
                                .position(point)
                                .snippet(property)
                        );
                    }
                } else {
                    marker = mapboxMap.addMarker(new MarkerViewOptions()
                            .position(point)
                            .snippet("No feature properties found")
                    );
                }

                //call this to invalidate view ;
                mMarkerAnimator = ObjectAnimator.ofObject(marker, "position", new TypeEvaluator<LatLng>() {
                    @Override
                    public LatLng evaluate(float fraction, LatLng startValue, LatLng endValue) {
                        return startValue;
                    }
                }, point);
                mMarkerAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        if (animation.getCurrentPlayTime() > 300)
                            mapboxMap.selectMarker(marker);
                    }
                });
                mMarkerAnimator.setDuration(500);
                mMarkerAnimator.setRepeatCount(0);
                mMarkerAnimator.start();

            }
        });
    }

    private void initMapBox(MapboxMap mapboxMap) {
        UiSettings uiSettings = mapboxMap.getUiSettings();
        mapboxMap.setDebugActive(false);
        uiSettings.setLogoEnabled(false);
        uiSettings.setCompassEnabled(false);
        uiSettings.setAttributionEnabled(false);
        uiSettings.setTiltGesturesEnabled(false);
        uiSettings.setRotateGesturesEnabled(false);
        uiSettings.setDeselectMarkersOnTap(true);

        mapboxMap.setAllowConcurrentMultipleOpenInfoWindows(false);
//        mapboxMap.setMyLocationEnabled(true);
        mapboxMap.setMinZoomPreference(MIN_ZOOM);
        mapboxMap.setMaxZoomPreference(MAX_ZOOM);

    }

}
